/**
 * 类型封装
 * @param properties
 * @returns {klass}
 * @constructor
 */
const Class = function (properties) {
    const klass = function () {
        if (this.initialize && arguments[0] != 'noinit') {
            return this.initialize.apply(this, arguments);
        } else return this;
    };
    for (let prop in this) {
        klass[prop] = this[prop];
    }
    klass.prototype = properties;
    return klass;
};


Class.empty = function () {
};

Class.prototype = {

    extend: function (properties) {
        const pr0t0typ3 = new this('noinit');

        const parentize = function (previous, current) {
            if (!previous.apply || !current.apply) return false;
            return function () {
                this.parent = previous;
                return current.apply(this, arguments);
            };
        };

        for (let property in properties) {
            const previous = pr0t0typ3[property];
            let current = properties[property];
            if (previous && previous != current) current = parentize(previous, current) || current;
            pr0t0typ3[property] = current;
        }
        return new Class(pr0t0typ3);
    },

    implement: function (properties) {
        for (let property in properties) {
            this.prototype[property] = properties[property];
        }
    }

};

Object.extend = function () {
    let args = arguments;
    args = (args[1]) ? [args[0], args[1]] : [this, args[0]];
    for (let property in args[1]) args[0][property] = args[1][property];
    return args[0];
};

Object.Native = function () {
    for (let i = 0; i < arguments.length; i++) arguments[i].extend = Class.prototype.implement;
};

new Object.Native(Function, Array, String, Number, Class);

/**
 * 回调函数对象
 * @type {klass}
 */
const CallerResponder = new Class({
    debug: false,
    context: new Object(),
    success: function (jsonObj) {
        let msg = "ajax success: " + jsonObj;
        if (this.debug) {
            console.debug(msg);
        }
    },
    error: function (reason) {
        console.error("ajax error: " + reason);
    },
    complete: function (res, status) {
        if (this.debug) {
            console.debug("ajax complete");
        }
    },
    beforeSend: function (xml) {
        if (this.debug) {
            console.debug("ajax beforeSend:" + xml);
        }
    }
});
//IE不支持fetch,实现方法
var initFetch=function(){
    window.fetch=function(url,params){
        let promise={
            then:function(fn){
                let xmlHttp = new XMLHttpRequest();
                xmlHttp.open(params.method,url,true);
                xmlHttp.onreadystatechange=function() {
                    if (xmlHttp.readyState==4 && xmlHttp.status==200) {
                        try {
                            fn(xmlHttp.responseText);
                        }catch (e) {
                            promise.error(e);
                        }
                    }
                }
                for(let he in params.headers){
                    xmlHttp.setRequestHeader(he,params.headers[he]);
                }
                xmlHttp.send(params.body);
                return promise;
            },
            'catch':function(fn){
                promise.error=fn;
            }
        }
        return promise;
    }
}
try{
    if(fetch==undefined){
        initFetch();
    }
}catch (e) {
   initFetch();
}
/**
 * 远程服务基类
 * @type {klass}
 */
const ApiService = new Class({
    /**需要传进来服务地址*/
    url: "/api/",
    async: true,
    /**需要传进来服务名称*/
    serviceName: "",
    headers: {
        'Content-Type': 'application/json',
        'strate-api-submit':'true'
    },
    suffix:"",
    /**AJAX处理方法*/
    ajaxCall: function (method, data, callerResponder) {
        //发送之前
        callerResponder.beforeSend(data)
        fetch(this.url + data.method+this.suffix, {
            method: method,
            body: data.arguments,
            headers: this.headers
        }).then(function (resp) {
            if( typeof(resp)=="string"){//IE下执行
                callerResponder.success(JSON.parse(resp));
            }else{
                resp.json().then(function (value) {
                    callerResponder.success(value);
                }).catch(function (reason) {
                    callerResponder.error(reason);
                });
            }

        }).catch(function (res) {
            callerResponder.error(res);
        });
        callerResponder.complete();
    },

    preprocess: function () {
        let callerResponder;
        if (arguments.length > 0) {
            const callbackIdx = arguments.length - 1;
            if (arguments[callbackIdx] instanceof CallerResponder) {
                callerResponder = arguments[callbackIdx];
                Array.prototype.splice.apply(arguments, [callbackIdx, 1]);
            } else if (arguments[callbackIdx] instanceof Function) {
                callerResponder = new CallerResponder();
                callerResponder.success = arguments[callbackIdx];
                Array.prototype.splice.apply(arguments, [callbackIdx, 1]);
            }
        }
        const newArgs = new Array();
        for (let i = 0; i < arguments.length; i++) {
            newArgs[i] = arguments[i];
        }
        if (!callerResponder) {
            callerResponder = new CallerResponder();
        }
        const data = new Object();
        data.service = this.serviceName;
        data.arguments = JSON.stringify(newArgs);
        const preprocessResult = new Object();
        preprocessResult.callerResponder = callerResponder;
        preprocessResult.data = data;
        return preprocessResult;
    }
});